import json
import os
import shutil
from tkinter import messagebox

class ConfigManager:
    """
    配置文件管理器，负责处理配置的加载、保存和迁移。
    """
    
    KNOWN_CONFIG_KEYS = {"left_long_press_time", "left_min_delay", "left_max_delay", 
                          "right_long_press_time", "right_min_delay", "right_max_delay", 
                          "shift_hold_time", "shift_interval", "enable_shift_click",
                          "fishing_mode_enabled", "fishing_weapon_slot", "fishing_rod_slot",
                          "fishing_cast_min_delay", "fishing_cast_max_delay", 
                          "fishing_attack_min_count", "fishing_attack_max_count",
                          "fishing_attack_min_delay", "fishing_attack_max_delay"}
    
    def __init__(self):
        # 默认配置目录：C:\Users\[当前用户]\.config\
        self.default_config_dir = os.path.join(r"C:\Users", os.getlogin(), ".config")
        self.default_config_filename = "minecraft-autoclick.acconfig"
        
        # 主设置文件(用于记录最后一次成功的config文件路径)
        self.main_settings_file = os.path.join(self.default_config_dir, "autoclicker_settings.json")
        
        # 若主设置文件中有记录，则读取，没有就用默认
        self.config_file_path = self.get_last_config_path() or os.path.join(
            self.default_config_dir, self.default_config_filename)
        
        # 确保默认配置目录存在
        if not os.path.exists(self.default_config_dir):
            os.makedirs(self.default_config_dir, exist_ok=True)
    
    def get_last_config_path(self):
        """获取上次使用的配置文件路径"""
        if not os.path.exists(self.main_settings_file):
            return None
        try:
            with open(self.main_settings_file, "r", encoding="utf-8") as f:
                data = json.load(f)
            return data.get("lastConfigFile", None)
        except:
            return None
    
    def save_last_config_path(self, path):
        """保存最后使用的配置文件路径"""
        data = {"lastConfigFile": path}
        os.makedirs(os.path.dirname(self.main_settings_file), exist_ok=True)
        with open(self.main_settings_file, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=4)
    
    def load_config_file(self, path, config_vars):
        """
        加载配置文件
        config_vars是一个字典，包含要设置的配置变量
        """
        if not os.path.exists(path):
            print(f"配置文件 {path} 不存在，创建默认配置文件。")
            self.write_default_config(path)
        else:
            with open(path, "r", encoding="utf-8") as f:
                try:
                    data = json.load(f)
                except json.JSONDecodeError:
                    messagebox.showerror("错误", f"配置文件 {path} 内容有误，将使用默认配置重新覆盖。")
                    self.write_default_config(path)
                    data = {}

                # 检查是否有未知项
                for key in data.keys():
                    if key not in self.KNOWN_CONFIG_KEYS:
                        raise ValueError("该文件包含未知配置项，请更换一个符合要求的文件")

                # 设置默认值（如果文件里缺）
                data.setdefault("left_long_press_time", 0.2)
                data.setdefault("left_min_delay", 0.05)
                data.setdefault("left_max_delay", 0.07)

                data.setdefault("right_long_press_time", 0.2)
                data.setdefault("right_min_delay", 0.05)
                data.setdefault("right_max_delay", 0.07)

                data.setdefault("shift_hold_time", 0.1)
                data.setdefault("shift_interval", 0.5)

                # 若 enable_shift_click 不存在，则默认False
                data.setdefault("enable_shift_click", False)
                
                # 鱼竿连点模式配置项
                data.setdefault("fishing_mode_enabled", False)
                data.setdefault("fishing_weapon_slot", 1)
                data.setdefault("fishing_rod_slot", 2)
                data.setdefault("fishing_cast_min_delay", 0.15)
                data.setdefault("fishing_cast_max_delay", 0.2)
                data.setdefault("fishing_attack_min_count", 10)
                data.setdefault("fishing_attack_max_count", 15)
                data.setdefault("fishing_attack_min_delay", 0.05)
                data.setdefault("fishing_attack_max_delay", 0.07)
                
                # 处理旧配置项的迁移
                if "fishing_attack_count" in data:
                    # 如果存在旧的单一攻击次数配置，将其转换为范围配置
                    old_count = data.pop("fishing_attack_count")
                    if "fishing_attack_min_count" not in data:
                        data["fishing_attack_min_count"] = max(1, old_count - 1)
                    if "fishing_attack_max_count" not in data:
                        data["fishing_attack_max_count"] = old_count + 1

                # 设置配置变量
                for key, var in config_vars.items():
                    if key in data:
                        var.set(data[key])

                self.save_config_file(path, config_vars)

        self.config_file_path = path
        self.save_last_config_path(path)
        return self.config_file_path
    
    def write_default_config(self, path):
        """写入默认配置文件"""
        default_data = {
            "left_long_press_time": 0.2,
            "left_min_delay": 0.05,
            "left_max_delay": 0.07,
            "right_long_press_time": 0.2,
            "right_min_delay": 0.05,
            "right_max_delay": 0.07,
            "shift_hold_time": 0.1,
            "shift_interval": 0.5,
            "enable_shift_click": False,
            "fishing_mode_enabled": False,
            "fishing_weapon_slot": 1,
            "fishing_rod_slot": 2,
            "fishing_cast_min_delay": 0.15,
            "fishing_cast_max_delay": 0.2,
            "fishing_attack_min_count": 10,
            "fishing_attack_max_count": 15,
            "fishing_attack_min_delay": 0.05,
            "fishing_attack_max_delay": 0.07
        }
        with open(path, "w", encoding="utf-8") as f:
            json.dump(default_data, f, indent=4)
    
    def save_config_file(self, path, config_vars):
        """保存配置到文件"""
        if not path:
            path = self.config_file_path

        if os.path.isdir(path):
            path = os.path.join(path, self.default_config_filename)
            self.config_file_path = path

        if not os.path.exists(path):
            self.write_default_config(path)

        try:
            with open(path, "r", encoding="utf-8") as f:
                data = json.load(f)
        except:
            data = {}

        # 检查未知项
        for key in data.keys():
            if key not in self.KNOWN_CONFIG_KEYS:
                messagebox.showerror("错误", "该文件包含未知配置项，请更换一个符合要求的文件")
                return

        # 从配置变量中更新数据
        for key, var in config_vars.items():
            data[key] = var.get()

        with open(path, "w", encoding="utf-8") as f:
            json.dump(data, f, indent=4)

        print(f"配置已保存到 {path}")
        self.save_last_config_path(path)
        return self.config_file_path
    
    def test_write_permission(self, directory):
        """测试目录是否有写入权限"""
        test_file = os.path.join(directory, "permission_test.tmp")
        try:
            with open(test_file, "w", encoding="utf-8") as f:
                f.write("test")
            os.remove(test_file)
            return True
        except (PermissionError, OSError):
            return False
    
    def move_config_file(self, old_path, new_path):
        """移动配置文件到新位置"""
        if not os.path.exists(old_path):
            return

        if os.path.isdir(new_path):
            final_path = os.path.join(new_path, self.default_config_filename)
            if not self.test_write_permission(new_path):
                messagebox.showerror("无权限", "无权限操作当前路径，请以管理员身份启动，或为该目录设置编辑权限")
                return
        else:
            final_path = new_path
            target_dir = os.path.dirname(final_path)
            if not os.path.exists(target_dir):
                try:
                    os.makedirs(target_dir, exist_ok=True)
                except PermissionError:
                    messagebox.showerror("无权限", "无权限操作当前路径，请以管理员身份启动，或为该目录设置编辑权限")
                    return
            if not self.test_write_permission(target_dir):
                messagebox.showerror("无权限", "无权限操作当前路径，请以管理员身份启动，或为该目录设置编辑权限")
                return

        if os.path.exists(final_path):
            try:
                os.remove(final_path)
            except PermissionError:
                messagebox.showerror("无权限", f"无法覆盖已有文件: {final_path}\n请以管理员身份启动或更改权限。")
                return

        try:
            shutil.move(old_path, final_path)
            print(f"已将配置文件从 {old_path} 移动到 {final_path}")
            return final_path
        except PermissionError:
            messagebox.showerror("无权限", "无权限操作当前路径，请以管理员身份启动，或为该目录设置编辑权限")
            return None 